package org.bling.star.server.connect.node;

import org.bling.star.common.connect.AbstractConnectClient;
import org.bling.star.common.connect.ConnectStatus;
import org.bling.star.common.model.UserInfo;
import org.bling.star.common.response.BaseResponse;
import org.bling.star.server.connect.GlobalConnectManager;
import org.bling.star.server.connect.StreamPool;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.util.concurrent.Promise;
import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @Describe: 客户端连接资源
 * @Date: 2024/5/9
 * @Author: szz
 */
public class InstanceConnection extends AbstractConnectClient {
    private static final Logger log = org.slf4j.LoggerFactory.getLogger(InstanceConnection.class);
    private Channel channel;
    private UserInfo userInfo;
    private Long lastAliveTime;
    private final List<StreamPool> streamPools;
    private ConnectStatus status;

    public UserInfo getUserInfo() {
        return this.userInfo;
    }

    public InstanceConnection(Channel channel) {
        this.channel = channel;
        this.streamPools = new ArrayList<>();
        this.lastAliveTime = System.currentTimeMillis();
        GlobalConnectManager.getInstance().addConnection(this);
    }

    public BaseResponse send(Object message) {
        if(isShutdown()) {
            log.error("连接已关闭");
            return BaseResponse.fail();
        }
        log.info("sending...channel:{},message:{}",channel.remoteAddress(),message.toString());
        Promise promise = send0(message);
        //服务端发完不是很care客户端的响应，可能后期改
        if(promise.isSuccess()) {
            log.info("send success");
            return BaseResponse.success(true);
        }else {
            log.info("send fail");
            return BaseResponse.fail();
        }
    }

    public void setMissing() {
        //todo szz 这个时间要统一配
        if(System.currentTimeMillis() - this.lastAliveTime > 10000) {
            this.status = ConnectStatus.MISSING;
        }
    }
    @Override
    public ChannelFuture sendFuture(Object msg) {
        return channel.writeAndFlush(msg);
    }

    @Override
    public Channel channel() {
        return channel;
    }

    public boolean close() {
        this.status = ConnectStatus.SHUTDOWN;
        for (StreamPool pool : streamPools) {
            pool.remove(this);
            log.info("channel:{},断开聊天室:{}",channel.remoteAddress(), pool.getStreamName());
        }
        streamPools.clear();
        try {
            ChannelFuture sync = this.channel.close().sync();
            if(sync.isSuccess()) {
                log.info("已关闭:{}", this.getUserInfo());
                this.channel = null;
                return true;
            }else {
                log.info("关闭失败:{}", this.getUserInfo());
                return false;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public ConnectStatus status() {
        return this.status;
    }

    public StreamPool getStreamPool(String streamSecretKey) {
        return streamPools.stream().filter(streamPool -> Objects.equals(streamPool.getStreamSecretKey().getStreamKey(), streamSecretKey)).findFirst().orElse(null);
    }

    public Boolean addStreamPool(StreamPool streamPool) {
        if (streamPools.contains(streamPool)) {
            return false;
        }
        streamPools.add(streamPool);
        return true;
    }
    public Channel getChannel() {
        return this.channel;
    }

    public Long getLastAliveTime() {
        return this.lastAliveTime;
    }

    public List<StreamPool> getStreamPools() {
        return this.streamPools;
    }


    public ConnectStatus getStatus() {
        return this.status;
    }

    public void setUserInfo(UserInfo userInfo) {
        this.userInfo = userInfo;
    }

    public void removeStreamPool(StreamPool streamPool) {
        streamPools.remove(streamPool);
    }

    public void alive() {
        this.lastAliveTime = System.currentTimeMillis();
        this.status = ConnectStatus.CONNECTED;
    }
}
